package top.jacktgq.candychat.service.impl;

import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;
import top.jacktgq.candychat.mapper.*;
import top.jacktgq.candychat.netty.pojo.enums.MsgSignFlagEnum;
import top.jacktgq.candychat.pojo.ChatMsg;
import top.jacktgq.candychat.pojo.FriendsRequest;
import top.jacktgq.candychat.pojo.MyFriend;
import top.jacktgq.candychat.pojo.Userinfo;
import top.jacktgq.candychat.pojo.enums.SearchUserinfoStatusEnum;
import top.jacktgq.candychat.pojo.vo.FriendRequestVO;
import top.jacktgq.candychat.pojo.vo.MyFriendVO;
import top.jacktgq.candychat.service.UserinfoService;
import top.jacktgq.candychat.utils.CandyFileUtils;
import top.jacktgq.candychat.utils.FastDFSClient;
import top.jacktgq.candychat.utils.QRCodeUtils;

import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * @Author CandyWall
 * @Date 2021/2/8--20:08
 * @Description
 */
@Service
public class UserinfoServiceImpl implements UserinfoService {
    public static String base_path;	//获取用户登录的系统目录
    static {
        base_path = System.getProperty("user.home");
    }

    @Autowired
    private UserinfoMapper userinfoMapper;

    @Autowired
    private MyFriendMapper myFriendMapper;

    @Autowired
    private Sid sid;

    @Autowired
    private QRCodeUtils qrCodeUtils;

    @Autowired
    private FastDFSClient fastDFSClient;

    @Autowired
    private FriendsRequestMapper friendsRequestMapper;

    @Autowired
    private UserinfoMapperCustom userinfoMapperCustom;

    @Autowired
    private ChatMsgMapper chatMsgMapper;

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    /**
     *
     * @param username
     * @return 判断用户名是否存在
     */
    public boolean queryUsernameIfExist(String username) {
        Userinfo userinfo = new Userinfo();
        userinfo.setUsername(username);
        Userinfo result = userinfoMapper.selectOne(userinfo);
        return result != null ;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Userinfo queryUserinfo(Userinfo userinfo) {
        userinfo.setCid(null);
        return userinfoMapper.selectOne(userinfo);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    /**
     * 用户登录
     */
    public Userinfo login(Userinfo userinfo) {
        // 验证cid
        //userinfo.setCid(null);
        return queryUserinfo(userinfo);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void regist(Userinfo userinfo) {
        // 直接将昵称设置为用户名
        userinfo.setId(sid.nextShort());

        // 为每一个用户生成一个唯一的二维码
        // 二维码表示的内容：candywall_qrcode:[username]
        String content = "candywall_qrcode:" + userinfo.getUsername();
        // 二维码图片存放的路径
        String qrCodePath = base_path + "/temp/tmp.jpg";
        qrCodeUtils.createQRCode(qrCodePath, content);
        MultipartFile qrCodeFile = CandyFileUtils.fileToMultipart(qrCodePath);
        String qrCodeUrl = null;
        try {
            qrCodeUrl = fastDFSClient.uploadQRCode(qrCodeFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 上传成功会获取到一个文件id，这个id是原图id
        userinfo.setQrcode(qrCodeUrl);

        userinfo.setFaceImage("");
        userinfo.setFaceImageBig("");

        userinfo.setNickname(userinfo.getUsername());
        // 注册用户
        userinfoMapper.insert(userinfo);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    /**
     * 设置图片的路径
     * @param userinfo
     */
    public Userinfo setFaceImageUrl(Userinfo userinfo) {
        userinfoMapper.updateByPrimaryKeySelective(userinfo);
        return queryUserinfoById(userinfo.getId());
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    /**
     * 根据id查询用户信息
     * @param userId
     * @return
     */
    public Userinfo queryUserinfoById(String userId) {
        return userinfoMapper.selectByPrimaryKey(userId);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    /**
     * 设置昵称
     * @param userinfo
     */
    public Userinfo setNickname(Userinfo userinfo) {
        userinfoMapper.updateByPrimaryKeySelective(userinfo);
        return queryUserinfoById(userinfo.getId());
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    /**
     * 前置条件查询
     *      1、搜索的用户不存在，返回[无此用户]
     *      2、搜索的用户是你自己，返回不能[添加自己]
     *      3、搜索的用户已经是我的好友，返回[该用户已经是你的好友]
     * @param friendUsername
     * @return
     */
    public Object preconditionSearchUserinfo(String myUserId, String friendUsername) {
        // 1、搜索的用户不存在，返回[无此用户]
        Userinfo userinfo = queryUserinfoByUsername(friendUsername);
        if (userinfo == null) {
            return SearchUserinfoStatusEnum.USER_NOT_EXIST.status;
        }

        // 2、搜索的用户是你自己，返回不能[添加自己]
        if (userinfo.getId().equals(myUserId)) {
            return SearchUserinfoStatusEnum.NOT_YOURSELF.status;
        }

        // 3、搜索的用户已经是我的好友，返回[该用户已经是你的好友]
        MyFriend myFriend = queryFriendByUserId(myUserId, userinfo.getId());
        if (myFriend != null) {
            return SearchUserinfoStatusEnum.ALREADY_FRIENDS.status;
        }

        return userinfo;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    /**
     * 根据用户ID查询朋友信息
     * @param myUserId
     * @param friendUserId
     * @return
     */
    protected MyFriend queryFriendByUserId(String myUserId, String friendUserId) {
        MyFriend friend = new MyFriend();
        friend.setMyUserId(myUserId);
        friend.setMyFriendUserId(friendUserId);
        return myFriendMapper.selectOne(friend);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    protected Userinfo queryUserinfoByUsername(String username) {
        Example userExample = new Example(Userinfo.class);
        Example.Criteria criteria = userExample.createCriteria();
        criteria.andEqualTo("username", username);

        return userinfoMapper.selectOneByExample(userExample);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    /**
     * 发送添加好友请求
     * @param myUserId
     * @param friendUserId
     */
    public void sendFriendRequest(String myUserId, String friendUserId) {
        FriendsRequest friendsRequest = new FriendsRequest();
        friendsRequest.setSendUserId(myUserId);
        friendsRequest.setAcceptUserId(friendUserId);
        // 查询记录是否已经存在
        FriendsRequest result = friendsRequestMapper.selectOne(friendsRequest);
        if (result != null) {
            return;
        }
        // 添加好友请求记录保存到数据库
        friendsRequest.setId(sid.nextShort());
        friendsRequest.setRequestDateTime(new Date());
        friendsRequestMapper.insert(friendsRequest);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    /**
     * 查询添加好友记录
     * @param acceptUserId
     * @return
     */
    public List<FriendRequestVO> queryFriendRequestList(String acceptUserId) {
        return userinfoMapperCustom.queryFriendRequestList(acceptUserId);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    /**
     * 处理好友请求：接受方通过、拒绝或者忽略朋友请求
     * 修改friends_request表中的request_status
     * request=1：通过
     * request=2：拒绝
     * request=3：忽略
     * @param friendsRequest
     * @return
     */
    public void operateFriendRequest(FriendsRequest friendsRequest) {
        //构建查询条件
        Example friendsRequestExample = new Example(FriendsRequest.class);
        Example.Criteria criteria = friendsRequestExample.createCriteria();
        criteria.andEqualTo("acceptUserId", friendsRequest.getAcceptUserId());
        criteria.andEqualTo("sendUserId", friendsRequest.getSendUserId());
        // 需要修改的字段赋值
        FriendsRequest updateValue = new FriendsRequest();
        updateValue.setRequestStatus(friendsRequest.getRequestStatus());
        // 执行修改操作
        friendsRequestMapper.updateByExampleSelective(updateValue, friendsRequestExample);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    /**
     * 通过请求，并且将查询当前用户所有朋友
     * @param friendsRequest
     */
    public List<MyFriendVO> passFriendRequest(FriendsRequest friendsRequest) {
        // 相互添加好友：在my_friend表中添加两条记录
        saveFriend(friendsRequest.getAcceptUserId(), friendsRequest.getSendUserId());
        saveFriend(friendsRequest.getSendUserId(), friendsRequest.getAcceptUserId());
        // 修改friends_request表中的request_status
        operateFriendRequest(friendsRequest);
        return getMyFriendsByUserId(friendsRequest.getAcceptUserId());
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void saveFriend(String sendUserId, String acceptUserId) {
        MyFriend myFriend = new MyFriend(sid.nextShort(), sendUserId, acceptUserId);
        myFriendMapper.insert(myFriend);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    /**
     * 加载通讯录：查询我的所有朋友
     */
    public List<MyFriendVO> getMyFriendsByUserId(String userId) {
        return userinfoMapperCustom.getMyFriends(userId);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    /**
     * Netty：保存消息
     * @param chatMsg
     */
    public void saveChatMsg(ChatMsg chatMsg) {
        chatMsg.setId(sid.nextShort());
        chatMsg.setCreateTime(new Date());
        chatMsg.setSignFlag(MsgSignFlagEnum.UNSIGN.type);
        chatMsgMapper.insert(chatMsg);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    /**
     * 批量签收消息
     * @param msgIdList
     */
    public void updateMsgSignedBatch(List<String> msgIdList) {
        userinfoMapperCustom.updateMsgSignedBatch(msgIdList);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    /**
     * 用户手机端获取未签收的消息列表
     * @param userId
     * @return
     */
    public List<ChatMsg> getUnsignedMsgListByUserId(String userId) {
        Example chatMsgExample = new Example(ChatMsg.class);
        chatMsgExample.createCriteria().andEqualTo("acceptUserId", userId)
                                        .andEqualTo("signFlag", 0);
        return chatMsgMapper.selectByExample(chatMsgExample);
    }
}
